#!/bin/bash
ASCEND_SECLOG="/var/log/ascend_seclog"
logFile="${ASCEND_SECLOG}/ascend_install.log"
installInfo="/etc/ascend_install.info"

SHELL_DIR=$(cd "$(dirname "$0")" || exit; pwd)
COMMON_SHELL="$SHELL_DIR/common.sh"
# load common.sh, get install.info
source "${COMMON_SHELL}"

CUR_DIR="$(dirname $(readlink -f "$0"))"
TOP_DIR="${CUR_DIR}/../../"
SRC_DIR="${TOP_DIR}/driver/kernel/"
SCENE_INFO="${TOP_DIR}/driver/scene.info"
DRV_DIR="${TOP_DIR}/driver/"
TAR_DIR="${DRV_DIR}"
DRV_BIN_DIR="${TOP_DIR}/driver/host_driver_binary/"
TAR_CSV=${DRV_BIN_DIR}/os_version.csv
TMP_TAR_DIR=""
closeltver_arr=(0)
closegtver_arr=(999999999)

STRICT_MATCH=y
DO_REBUILD=n
ADVANCED_FUZZY=n

log() {
    cur_date=`date +"%Y-%m-%d %H:%M:%S"`
    user_id=`id | awk '{printf $1}'`
    echo "[Driver] [$cur_date] [$user_id] "$1 >> $logFile
}

drvEcho() {
    cur_date=`date +"%Y-%m-%d %H:%M:%S"`
    echo "[Driver] [$cur_date] $1"
}

# return 0: arr1 == arr2; return 1: arr1 < arr2; return 2: arr1 > arr2
arr_cmp() {
    local arr1=($1)
    local arr2=($2)
    for ((i=0; i<${#arr1[@]} && i<${#arr2[@]}; i++))
    do
        if [ `expr ${arr1[i]}` -lt `expr ${arr2[i]}` ]; then
            return 1
        elif [ `expr ${arr1[i]}` -gt `expr ${arr2[i]}` ]; then
            return 2
        fi
    done
    if [ ${#arr1[@]} -eq ${#arr2[@]} ]; then
        return 0
    elif [ ${#arr1[@]} -lt ${#arr2[@]} ]; then
        return 1;
    else
        return 2;
    fi
}

modversion_fuzzy_match() {
    # check euleros V-R version is mapped, such as eulerosv2r9
    if [[ $kernel_ver =~ "euleros" ]] && [[ $ko_vermagic =~ "euleros" ]]; then
        kernel_vr_version=$(echo $kernel_ver | awk -F 'euleros' '{print $NF}' | awk -F '.' '{print $1}')
        ko_vr_version=$(echo $ko_vermagic | awk -F 'euleros' '{print $NF}' | awk -F '.' '{print $1}')
        if [ "$kernel_vr_version"x != "$ko_vr_version"x ]; then
            DO_REBUILD=y
            return
        fi
    fi
    primary_kernel_ver=$(echo $kernel_ver | awk -F [-+] '{print $1}')
    primary_ko_vermagic=$(echo $ko_vermagic | awk -F [-+] '{print $1}')
    if [ "$primary_kernel_ver"x != "$primary_ko_vermagic"x ];then
        DO_REBUILD=y
    else
        # temporary for 910B, delete in the future
        if [ ! -n "$arch_type" ]; then
            arch_type="aarch64"
        fi
        local minor_kernel_ver=$(echo $kernel_ver | awk -F [-+] '{print $2}'| awk -F 'euleros' '{print $1}'| awk -F $arch_type '{print $1}')
        local minor_ko_vermagic=$(echo $ko_vermagic | awk -F [-+] '{print $2}'| awk -F 'euleros' '{print $1}'| awk -F $arch_type '{print $1}')
        local basever_arr=(`echo $minor_kernel_ver | tr -dc "[0-9._]"| tr "[._]" ' '`)
        local cmpver_arr=(`echo $minor_ko_vermagic | tr -dc "[0-9._]"| tr "[._]" ' '`)
        local lt_flag=$1
        if [ "${lt_flag}"x = "y"x ]; then
            arr_cmp "${cmpver_arr[*]}" "${basever_arr[*]}"
            local res1=$?
            arr_cmp "${cmpver_arr[*]}" "${closeltver_arr[*]}"
            local res2=$?
            if [ $res1 -eq 1 ] && [ $res2 -eq 2 ]; then
                closeltver_arr=(${cmpver_arr[@]})
                TMP_TAR_DIR=$TAR_DIR
            fi
        else
            arr_cmp "${cmpver_arr[*]}" "${basever_arr[*]}"
            local res1=$?
            arr_cmp "${cmpver_arr[*]}" "${closegtver_arr[*]}"
            local res2=$?
            if [ $res1 -eq 2 ] && [ $res2 -eq 1 ]; then
                closegtver_arr=(${cmpver_arr[@]})
                TMP_TAR_DIR=$TAR_DIR
            fi
        fi
    fi
}

modversion_strict_match() {
    if [ "$kernel_ver"x != "$ko_vermagic"x ];then
        DO_REBUILD=y
    else
        log "[INFO]current kernel primary version($kernel_ver) match the driver($ko_vermagic)."
        DO_REBUILD=n
    fi
}

check_euleros() {
    source "${TOP_DIR}"/driver/script/common_func.inc
    source "${TOP_DIR}"/driver/scene.info

    get_system_info
    log "[INFO]HostOsName(${HostOsName})"
    if [ "${HostOsName}"x == "EulerOS"x ]; then
        for item in ${os}
        do
            if echo $item | grep -i "^${HostOsName}$">/dev/null;then
                log "[INFO]os($HostOsName) try fuzzy match"
                STRICT_MATCH=n
                return
            fi
        done
    fi
}

find_and_match() {
    local para_line=$1
    local force_flag=$2
    local os_ver=`echo ${para_line} | awk -F ',' '{print $1}'`
    local ker_ver=`echo ${para_line} | awk -F ',' '{print $2}'`
    arch_type=`echo ${para_line} | awk -F ',' '{print $3}'`
    local match_type=`echo ${para_line} | awk -F ',' '{print $4}'`

    # match modversion
    if ([ "${HostOsName}"x = "EulerOS"x ] || [ "${HostOsFullName}"x = "Huawei Cloud EulerOS"x ]) && [ "${match_type}"x = "fuzzy"x ] \
        && [ "${force_flag}"x != "y"x ]; then
        STRICT_MATCH=n
    else
        STRICT_MATCH=y
    fi

    # match fuzzy os
    if [ "${STRICT_MATCH}"x = "n"x ]; then
        if [ "${HostOsFullName}"x = "Huawei Cloud EulerOS"x ]; then
            echo ${os_ver} | grep -i "openeuler" >/dev/null || return 1
        else
            echo ${os_ver} | grep -i "^${HostOsName}$" >/dev/null || return 1
        fi
    fi

    TAR_DIR="${DRV_BIN_DIR}/${os_ver}_${ker_ver}"
    check_and_match $3
    if [ "${STRICT_MATCH}"x = "y"x ] && [ "${DO_REBUILD}"x = "n"x ]; then
        log "[INFO]driver modversion(${ker_ver}) match success, tar dir is ${os_ver}_${ker_ver}"
        return 0
    fi
    return 1
}

check_and_match() {
    pcie_hdc_ko="${TAR_DIR}"/host/drv_pcie_hdc_host.ko
    kernel_ver=$(getKernelVer)
    ko_vermagic=$(modinfo "$pcie_hdc_ko" | grep vermagic | awk '{print $2}')

    if [ "${STRICT_MATCH}"x = "y"x ]; then
        modversion_strict_match
    else
        modversion_fuzzy_match $1
    fi
}

find_host_bin() {
    [ -e "${TAR_CSV}" ] || { log "[WARNING]os_version.csv is no exist." && return 1; }

    # first match use strict type
    force_flag=y
    while read line
    do
        find_and_match ${line} ${force_flag} && return 0
    done < ${TAR_CSV}

    # fuzzy match
    force_flag=n
    lt_flag=y
    while read line
    do
        find_and_match ${line} ${force_flag} ${lt_flag}
    done < ${TAR_CSV}
    if [ "${TMP_TAR_DIR}"x != ""x ]; then
        TAR_DIR=$TMP_TAR_DIR
        local REL_TAR_DIR=${TAR_DIR##*/}
        log "[INFO]driver modversion(${REL_TAR_DIR#*_}) match success, tar dir is ${REL_TAR_DIR}"
        DO_REBUILD=n
        return 0
    else
        lt_flag=n
        while read line
        do
        find_and_match ${line} ${force_flag} ${lt_flag}
        done < ${TAR_CSV}
        if [ "${TMP_TAR_DIR}"x != ""x ]; then
            TAR_DIR=$TMP_TAR_DIR
            local REL_TAR_DIR=${TAR_DIR##*/}
            log "[INFO]driver modversion(${REL_TAR_DIR#*_}) match success, tar dir is ${REL_TAR_DIR}"
            DO_REBUILD=n
            return 0
        fi
    fi

    return 1
}

copy_match_bin_to_host() {
    cp -arf ${TAR_DIR}/* ${DRV_DIR} || exit 1
}

# start
# check host match or not
check_euleros
check_and_match
if [ "${DO_REBUILD}"x = "y"x ]; then
    log "[INFO]driver ko vermagic($ko_vermagic) is different from the os($kernel_ver), need change host driver binary"
    find_host_bin || DO_REBUILD=y
    if [ "${DO_REBUILD}"x = "y"x ]; then
        log "[INFO]there is no driver modversion can match current kernel($kernel_ver), try to rebuild."
        drvEcho "[INFO]driver install type: Rebuild"
        bash ${CUR_DIR}/run_driver_ko_rebuild.sh || { log "[ERROR]driver rebuild failed." && exit 1; }
        exit 0
    else
        log "[INFO]change host driver binary success"
        copy_match_bin_to_host
    fi
fi
drvEcho "[INFO]driver install type: Direct"
exit 0
